﻿using System;
using System.Collections.Generic;
using System.Text;
using WatiN.Core.Constraints;
using WatiN.Core.Interfaces;
using com.gargoylesoftware.htmlunit;
using com.gargoylesoftware.htmlunit.html;

namespace WatiN.Core.HtmlUnit
{
	public class HUBrowser : INativeBrowser
	{
		bool javascriptEnabled = true;
		DomContainer domContainer;
		HtmlPage currentPage;
		WebClient client;

		public HtmlPage CurrentPage
		{
			get
			{
				// return (HtmlPage)client.getCurrentWindow().getEnclosedPage();
				return currentPage; 
			}
			set 
			{
				currentPage = value; 
			}
		}

		public WebClient Client
		{
			get { return client; }
			set { client = value; }
		}

		public bool JavascriptEnabled
		{
			get
			{
				return javascriptEnabled;
			}
			set
			{
				client.setJavaScriptEnabled(value);
				javascriptEnabled = value;
			}
		}

		public HUBrowser(DomContainer domContainer, BrowserVersion browserType)
		{
			this.domContainer = domContainer;
			client = new WebClient(browserType);
			client.setThrowExceptionOnScriptError(false);
		}

		public HUBrowser(DomContainer domContainer, ProxyConfig proxyConfig)
		{
			this.domContainer = domContainer;
			client = new WebClient();
			client.setThrowExceptionOnScriptError(false);
			client.setProxyConfig(proxyConfig);
		}

		public HUBrowser(DomContainer domContainer, BrowserVersion browserType, string proxyAddress, int proxyPort, string username, string password)
		{
			this.domContainer = domContainer;
			client = new WebClient(browserType);
			client.setThrowExceptionOnScriptError(false);
			var prov = new DefaultCredentialsProvider();
			var cfg = new ProxyConfig(proxyAddress, proxyPort);
			prov.addProxyCredentials(username, password, proxyAddress, proxyPort);
			client.setProxyConfig(cfg);
			client.setCredentialsProvider(prov);
		}

		public HUBrowser(DomContainer domContainer, ProxyConfig proxyConfig, BrowserVersion browserType)
		{
			this.domContainer = domContainer;
			client = new WebClient(browserType);
			client.setThrowExceptionOnScriptError(false);
			client.setProxyConfig(proxyConfig);
		}

		public HUBrowser(DomContainer domContainer)
		{
			this.domContainer = domContainer;
			client = new WebClient(BrowserVersion.INTERNET_EXPLORER_7);
			client.setThrowExceptionOnScriptError(false);
		}

		public void Navigate(Uri uri)
		{
			try
			{
				currentPage = (HtmlPage)client.getPage(uri.ToString());
			}
			catch (ScriptException)
			{
			}
		}

		public HtmlPage EnclosedPage
		{
			get { return (HtmlPage)client.getCurrentWindow().getEnclosedPage(); }
		}
		
		#region INativeBrowser Members
		public INativeElementFinder CreateElementFinder(List<ElementTag> tags, BaseConstraint baseConstraint, IElementCollection elements)
		{
			return new HUElementFinder(tags, baseConstraint, elements, domContainer);
		}

		public INativeElementFinder CreateElementFinder(List<ElementTag> tags, IElementCollection elements)
		{
			return new HUElementFinder(tags, elements, domContainer);
		}

		public INativeElementFinder CreateElementFinder(string tagname, string inputtypesString, BaseConstraint baseConstraint, IElementCollection elements)
		{
			return new HUElementFinder(tagname, inputtypesString, baseConstraint, elements, domContainer);
		}

		public INativeElement CreateElement(object element)
		{
			string strElement = element as string;

			if (!string.IsNullOrEmpty(strElement))
				throw new Exception("Element must be a string name of an element!");

			HtmlElement elem = currentPage.getElementById(strElement);

			return new HUElement(elem, this);
		}

		public INativeDocument CreateDocument(object document)
		{
			return new HUDocument(CurrentPage, this);
		}

		#endregion
	}
}
